package com.andova.egl

import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.os.Message
import com.andova.glcamera.MSG_EGL_HELPER_WHAT_DELAY_TASK
import com.andova.glcamera.MSG_EGL_HELPER_WHAT_INIT
import com.andova.glcamera.MSG_EGL_HELPER_WHAT_RENDER
import com.andova.glcamera.MSG_EGL_HELPER_WHAT_RESUME

data class EglMessage(
    val what: Int,
    val flag: Int,
    val width: Int,
    val height: Int,
    val format: Int,
    val delayMillis: Long
)

interface EglThreadHandler {
    fun handleMessage(what: Int)
    fun handleMessage(what: Int, width: Int, height: Int, format: Int)
    fun handleMessageDelayed(what: Int, flag: Int, delayMillis: Long)
    fun removeCallbacksAndMessages()
    fun startHandler()
    fun quitHandler()
    fun setListener(listener: OnEglThreadListener)
}

internal class TextureHandler(looper: Looper) : Handler(looper) {
    private var mListener: OnEglThreadListener? = null
    fun setListener(listener: OnEglThreadListener?) {
        mListener = listener
    }

    override fun handleMessage(msg: Message) {
        when (msg.what) {
            MSG_EGL_HELPER_WHAT_INIT -> mListener?.onInitTexEglContext(msg.arg1, msg.arg2, msg.obj as Int)
            MSG_EGL_HELPER_WHAT_RENDER -> mListener?.onTextureFrame()
            MSG_EGL_HELPER_WHAT_RESUME -> mListener?.onUpdateTexImage()
            MSG_EGL_HELPER_WHAT_DELAY_TASK -> mListener?.onDelayTask(msg.arg1)
        }
    }
}

internal class EglTextureHThread(name: String) : HT(name) {
    override fun handler(): TextureHandler? = mHdr
    private var mHdr: TextureHandler? = null
    override fun setListener(listener: OnEglThreadListener) {
        if (isAlive) mHdr?.setListener(listener)
    }

    override fun startHandler() {
        super.startHandler()
        mHdr = TextureHandler(looper)
    }

    override fun quitHandler() {
        super.quitHandler()
        mHdr?.setListener(null)
        mHdr = null
    }
}

internal class TaskHandler(looper: Looper) : Handler(looper) {
    private var mListener: OnEglThreadListener? = null
    fun setListener(listener: OnEglThreadListener?) {
        mListener = listener
    }

    override fun handleMessage(msg: Message) {
        when (msg.what) {
            MSG_EGL_HELPER_WHAT_INIT -> {
                mListener?.onInitTaskEglContext(msg.arg1, msg.arg2)
//                    sendEmptyMessage(MSG_EGL_HELPER_WHAT_RENDER)
            }
            MSG_EGL_HELPER_WHAT_RENDER -> {
                mListener?.onTaskFrame()
//                    sendEmptyMessage(MSG_EGL_HELPER_WHAT_RENDER)
            }
            MSG_EGL_HELPER_WHAT_DELAY_TASK -> mListener?.onDelayTask(msg.arg1)
        }
    }
}

internal class EglTaskHThread(name: String) : HT(name) {
    override fun handler(): TaskHandler? = mHdr
    private var mHdr: TaskHandler? = null
    override fun setListener(listener: OnEglThreadListener) {
        if (isAlive) mHdr?.setListener(listener)
    }

    override fun startHandler() {
        super.startHandler()
        mHdr = TaskHandler(looper)
    }

    override fun quitHandler() {
        super.quitHandler()
        mHdr?.setListener(null)
        mHdr = null
    }
}

abstract class HT(name: String) : HandlerThread(name), EglThreadHandler {
    override fun handleMessage(what: Int): Unit = run { if (isAlive) handler()?.sendEmptyMessage(what) }
    override fun handleMessage(what: Int, width: Int, height: Int, format: Int): Unit = run { if (isAlive) handler()?.sendMessage(Message.obtain(handler(), what, width, height, format)) }
    override fun handleMessageDelayed(what: Int, flag: Int, delayMillis: Long): Unit = run { if (isAlive) handler()?.sendMessageDelayed(Message.obtain(handler(), what, flag, 0), delayMillis) }
    override fun removeCallbacksAndMessages() {
        handler()?.removeCallbacksAndMessages(null)
    }

    override fun quitHandler() {
        quit()
        removeCallbacksAndMessages()
    }

    override fun startHandler() {
        if (state != State.NEW) return
        start()
    }

    abstract fun handler(): Handler?
}

@Deprecated("")
internal abstract class EglHT(name: String) : Thread(name), EglThreadHandler {
    @Volatile
    private var meglmsg: EglMessage? = null

    @Volatile
    private var mawait = Object()

    @Volatile
    private var mlock = false

    private var mloop = true
    private var mlistener: OnEglThreadListener? = null
    override fun handleMessage(what: Int) {
        if (mlock) return
        mlock = true
        meglmsg = EglMessage(what, 0, 0, 0, 0, 0)
        synchronized(mawait) { mawait.notify() }
    }

    override fun handleMessage(what: Int, width: Int, height: Int, format: Int) {
        if (mlock) return
        mlock = true
        meglmsg = EglMessage(what, 0, width, height, format, 0)
        synchronized(mawait) { mawait.notify() }
    }

    override fun handleMessageDelayed(what: Int, flag: Int, delayMillis: Long) {
        if (mlock) return
        mlock = true
        meglmsg = EglMessage(what, 0, 0, 0, 0, delayMillis)
        synchronized(mawait) { mawait.notify() }
    }

    override fun quitHandler() {
        if (state != State.TERMINATED) return
        mlistener = null
        mloop = false
    }

    override fun startHandler() {
        if (state != State.NEW) return
//        mlistener = listener
        start()
        mloop = true
    }

    final override fun run() {
        while (mloop) {
            synchronized(mawait) {
                if (meglmsg == null) {
                    handleMessage(null, mlistener)
                    mawait.wait()
                } else mawait.notify()
            }
            handleMessage(meglmsg, mlistener)
            meglmsg = null
            mlock = false
        }
    }

    abstract fun handleMessage(msg: EglMessage?, listener: OnEglThreadListener?)
}